package com.agv.backend.service.impl;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.agv.backend.entity.AgvResponse;
import com.agv.backend.entity.pojo.AgvConfig;
import com.agv.backend.entity.pojo.AgvTask;
import com.agv.backend.entity.AjaxResult;
import com.agv.backend.entity.vo.AgvUploadInfoVO;
import com.agv.backend.mapper.AgvTaskMapper;
import com.agv.backend.service.AgvConfigService;
import com.agv.backend.service.AgvFlawService;
import com.agv.backend.service.AgvMovementService;
import com.agv.backend.service.AgvTaskService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
@Slf4j
public class AgvTaskServiceImpl extends ServiceImpl<AgvTaskMapper, AgvTask> implements AgvTaskService {

    private final AgvTaskMapper agvTaskMapper;
    private final AgvMovementService agvMovementService;
    private final AgvFlawService agvFlawService;
    private final AgvConfigService agvConfigService;
    private final RestTemplate restTemplate;

    private static final String BASE_URL = "http://192.168.2.57/prod-api";

    public AgvTaskServiceImpl(AgvTaskMapper agvTaskMapper, AgvMovementService agvMovementService, AgvFlawService agvFlawService, AgvConfigService agvConfigService, RestTemplate restTemplate) {
        this.agvTaskMapper = agvTaskMapper;
        this.agvMovementService = agvMovementService;
        this.agvFlawService = agvFlawService;
        this.agvConfigService = agvConfigService;
        this.restTemplate = restTemplate;
    }

    @Override
    public List<AgvTask> selectAgvTaskList(AgvTask task) {
        QueryWrapper<AgvTask> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().like(StrUtil.isNotBlank(task.getTaskCode()), AgvTask::getTaskCode, task.getTaskCode())
                .like(StrUtil.isNotBlank(task.getCreator()), AgvTask::getCreator, task.getCreator())
                .like(StrUtil.isNotBlank(task.getExecutor()), AgvTask::getExecutor, task.getExecutor())
                .eq(StrUtil.isNotBlank(task.getTaskStatus()), AgvTask::getTaskStatus, task.getTaskStatus())
                .orderByDesc(AgvTask::getCreateTime);
        return agvTaskMapper.selectList(queryWrapper);
    }

    @Override
    public AgvTask selectAgvTaskById(Long id) {
        return agvTaskMapper.selectById(id);
    }

    @Override
    public int insertAgvTask(AgvTask task) {
        task.setTaskStatus(STATUS_WAITING);
        task.setCreateTime(new Date());
        task.setRound(0);
        return agvTaskMapper.insert(task);
    }

    @Override
    public int updateAgvTask(AgvTask task) {
        return agvTaskMapper.updateById(task);
    }

    @Override
    public int deleteAgvTaskById(Long id) {
        AgvTask agvTask = agvTaskMapper.selectById(id);
        if(STATUS_PATROLLING.equals(agvTask.getTaskStatus())){
            return -1;
        }

        return agvTaskMapper.deleteById(id);
    }

    @Override
    public AjaxResult startTask(Long id) {
        AgvTask agvTask = agvTaskMapper.selectById(id);
        if(agvTask == null) {
            return AjaxResult.error("任务不存在");
        }

        if(STATUS_DONE.equals(agvTask.getTaskStatus())) {
            return AjaxResult.error(String.format("任务%s已完成，无法重新开始", agvTask.getTaskCode()));
        }

        if(STATUS_PATROLLING.equals(agvTask.getTaskStatus())) {
            return AjaxResult.error(String.format("任务%s正在巡视中，无法重新开始", agvTask.getTaskCode()));
        }

        if(STATUS_PENDING.equals(agvTask.getTaskStatus())) {
            return AjaxResult.error(String.format("任务%s已巡视完成，无法重新开始", agvTask.getTaskCode()));
        }

        LambdaQueryWrapper<AgvTask> lambdaQueryWrapper = new LambdaQueryWrapper<AgvTask>().eq(AgvTask::getTaskStatus, STATUS_PATROLLING);
        List<AgvTask> agvTasks = agvTaskMapper.selectList(lambdaQueryWrapper);
        if(agvTasks!=null && !agvTasks.isEmpty()){
            AgvTask currentTask = agvTasks.get(0);
            return AjaxResult.error(String.format("任务%s正在巡视中，请稍后再试", currentTask.getTaskCode()));
        }

        if (agvMovementService.getHeartbeat().getData().getIsRunning()) {
            return AjaxResult.error(String.format("任务%s启动失败", agvTask.getTaskCode()));
        }

        agvTask.setTaskStatus(STATUS_PATROLLING);
        agvTask.setRound(agvTask.getRound() + 1);
        agvTask.setExecTime(new Date());
        return AjaxResult.success(agvTaskMapper.updateById(agvTask));
    }

    @Override
    public AjaxResult endTask(Long id, boolean isAbort) {
        AgvTask agvTask = agvTaskMapper.selectById(id);
        if(!STATUS_PATROLLING.equals(agvTask.getTaskStatus())) {
            return AjaxResult.error(String.format("任务%s不是巡视中状态，无法结束", agvTask.getTaskCode()));
        }

        boolean stop = agvMovementService.stop();
        if (!stop) {
            return AjaxResult.error(String.format("任务%s结束失败", agvTask.getTaskCode()));
        }

        agvTask.setTaskStatus(isAbort ? STATUS_WAITING : STATUS_PENDING);
        agvTask.setEndTime(new Date());
        return AjaxResult.success(agvTaskMapper.updateById(agvTask));
    }

    @Override
    public List<AgvUploadInfoVO> preUploadTask(Long id) {
        AgvTask agvTask = agvTaskMapper.selectById(id);

        List<AgvUploadInfoVO> uploadInfoVOList = new ArrayList<>();
        if(agvTask == null) {
            return List.of();
        }

        if(!agvTask.getUploaded()){
            uploadInfoVOList.add(new AgvUploadInfoVO(agvTask.getTaskName(), "巡视任务", "未上传"));
        }

        agvFlawService.liveInfo(id).stream()
                .filter(agvFlaw -> !agvFlaw.isUploaded())
                .map(agvFlaw -> new AgvUploadInfoVO(agvFlaw.getFlawName(), "故障信息", "未上传"))
                .forEach(uploadInfoVOList::add);

        return uploadInfoVOList;
    }

    @Override
    @Transactional
    public int uploadTask(Long id) {
        String url = BASE_URL + "/agv/task/upload/" + id;
        AgvResponse agvResponse = restTemplate.postForObject(url, null, AgvResponse.class);
        log.info("upload result: {}",agvResponse);
        // TODO:

        AgvTask agvTask = agvTaskMapper.selectById(id);
        agvTask.setTaskStatus(STATUS_DONE);
        int result = agvTaskMapper.updateById(agvTask);
        return result;
    }

    @Override
    public List<AgvTask> getTasksByTime(String startTime, String endTime) {
        return agvTaskMapper.selectList(new QueryWrapper<AgvTask>().between("end_time", startTime, endTime));
    }


}
